package repl

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"showen/eval"
	"showen/lex"
	"showen/obj"
	"showen/parse"
	"showen/tok"
	"strings"
)

const PROMPT = ">>> "
const CONTINUATION_PROMPT = "... "

func StartTerminal(in *bufio.Reader, out *bufio.Writer) {
	globalEnv := obj.NewEnvironment()

	eval.RegisterBuiltinProcedures(globalEnv)
	eval.LoadLibrary(globalEnv)

	printWelcomeMessage(out)
	flushWriter(out)
	for {
		fmt.Fprintf(out, PROMPT)
		flushWriter(out)

		var input strings.Builder
		for {
			line, err := in.ReadString('\n')
			if err != nil {
				if err == io.EOF {
					if len(strings.TrimSpace(line)) > 0 {
						input.WriteString(line)
						evalExpression(input.String(), out, globalEnv)
					}
					flushWriter(out)
					return
				}
				fmt.Fprintf(out, "Error reading input: %s\n", err)
				flushWriter(out)
				return
			}

			// 添加当前行到输入
			input.WriteString(line)

			// 检查是否需要更多输入（括号是否匹配）
			if needsMoreInput(input.String()) {
				// 如果是交互模式，显示续行提示符
				fmt.Fprintf(out, CONTINUATION_PROMPT)
				flushWriter(out)
				continue
			}

			// 括号匹配完成，跳出循环
			break
		}

		// 处理退出命令（仅在交互模式下）
		trimmed := strings.TrimSpace(input.String())
		if trimmed == "(exit)" || trimmed == "(quit)" {
			flushWriter(out)
			return
		}
		// 处理空输入
		if strings.TrimSpace(input.String()) == "" {
			continue
		}

		// 执行表达式
		evalExpression(input.String(), out, globalEnv)

	}
}

// needsMoreInput checks if the input needs more lines to complete
// by checking if all parentheses are balanced and strings are closed
func needsMoreInput(input string) bool {
	// Create a lexer to tokenize the input
	l := lex.NewLexer(input)

	// Count parentheses
	leftParenCount := 0
	rightParenCount := 0

	for {
		token := l.NextToken()
		if token.Type == tok.EOF {
			break
		}

		switch token.Type {
		case tok.LPAREN:
			leftParenCount++
		case tok.RPAREN:
			rightParenCount++
		case tok.ILLEGAL:
			// Check if this is an unclosed string
			if len(token.Lexeme) > 0 && token.Lexeme[0] == '"' {
				// This looks like the start of a string but it's not properly closed
				return true
			}
		}
	}

	// If we have more left parentheses than right ones, we need more input
	return leftParenCount > rightParenCount
}

// isInteractive checks if the input is coming from a terminal

// printWelcomeMessage打印欢迎信息
func printWelcomeMessage(out *bufio.Writer) {
	fmt.Fprintln(out, "Welcome to Showen!")
	fmt.Fprintln(out, "Type an expression to evaluate, or (exit) to quit.")
}

// flushWriter刷新写入器，确保输出显示
func flushWriter(out *bufio.Writer) {
	if err := out.Flush(); err != nil {
		fmt.Fprintf(os.Stderr, "Error flushing output: %s\n", err)
	}
}

// evalExpression执行表达式并输出结果
func evalExpression(input string, out *bufio.Writer, env *obj.Environment) {
	// 创建词法分析器
	l := lex.NewLexer(input)
	tokens := l.ReadTokens()
	correct := true
	for _, token := range tokens {
		if token.Type == tok.ILLEGAL {
			fmt.Fprintf(out, "Syntax Error: %s in %v:%v\n", token.Lexeme, token.Line, token.Column)
			flushWriter(out)
			correct = false
		}
	}
	if !correct {
		return
	}

	// 创建解析器
	p := parse.NewParser(tokens)

	// 解析表达式
	exprs, err := p.ParseProgram()
	if err != nil {
		fmt.Fprintf(out, "Parse error: %s\n", err)
		flushWriter(out)
		return
	}

	for _, expr := range exprs {
		if expr == nil {
			return
		}
		result, err := eval.EvalExpression(expr, env)
		if err != nil {
			fmt.Fprintf(out, "Eval error: %s\n", err)
			flushWriter(out)
			return
		}

		printResult(result, out)
	}
}

// printResult打印表达式的评估结果
func printResult(result obj.Object, out *bufio.Writer) {
	if result == obj.NULL_OBJECT {
		return
	}
	// Skip printing if the object implements NoPrint and returns true
	fmt.Fprintln(out, result.Inspect())
	flushWriter(out)
}

/*

func load(in *bufio.Reader, out *bufio.Writer, globalEnv obj.Environment) {
	var input strings.Builder
	for {
		line, err := in.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				if len(line) == 0 {
					break
				}
			} else {
				fmt.Println("Error reading input:", err)
				return
			}
		}

		// 添加当前行到输入
		input.WriteString(line)

		// 检查是否需要更多输入（括号是否匹配）
		if needsMoreInput(input.String()) {
			continue
		}

		// 处理退出命令（仅在交互模式下）
		trimmed := strings.TrimSpace(input.String())

		if len(trimmed) > 9 && trimmed[:5] == "(load" && unicode.IsSpace(rune(trimmed[5])) {
			l := lex.NewLexer(trimmed)
			p := par.NewParser(l)

			expr, err := p.ParseExpression()
			if err != nil {
				fmt.Println("parse error:", err)
				return
			}

			list, ok := expr.(*ast.ListExpression)
			if !ok {
				return
			}

			file, err := os.Open(list.Elements[1].TokenLiteral())
			if err != nil {
				fmt.Println("Error opening file:", err)
				return
			}
			defer file.Close()

			in := bufio.NewReader(file)
			out := bufio.NewWriter(os.Stdout)

			load(in, out, globalEnv)
		}

		if strings.TrimSpace(input.String()) == "" {
			continue
		}
		evalExpression(trimmed, out, globalEnv)
		input.Reset()

	}
}
*/
